﻿/*
 * Author: Gabriel Reiser
 * Contributors:
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Irrlicht.Net.Core
{
    [Serializable]
    public struct Vector2D
    {
        public float x;
        public float y;

        public float X { get { return x; } set { x = value; } }
        public float Y { get { return y; } set { y = value; } }
        public float Length { get { return (float)Math.Sqrt(x * x + y * y); } }
        public float LengthSquared { get { return x * x + y * y; } }
        public static readonly Vector2D Zero = new Vector2D(0.0f, 0.0f);
        public static readonly Vector2D UnitX = new Vector2D(1.0f, 0.0f);
        public static readonly Vector2D UnitY = new Vector2D(0.0f, 1.0f);
        public static readonly Vector2D Unit = new Vector2D(1.0f, 1.0f);

        public Vector2D(float x, float y)
        {
            this.x = x;
            this.y = y;
        }

        public static Vector2D operator +(Vector2D vec1, Vector2D vec2)
        {
            return new Vector2D(vec1.x + vec2.x, vec1.y + vec2.y);
        }

        public static Vector2D operator -(Vector2D vec1, Vector2D vec2)
        {
            return new Vector2D(vec1.x - vec2.x, vec1.y - vec2.y);
        }

        public static Vector2D operator -(Vector2D vec1, float value)
        {
            return new Vector2D(vec1.x - value, vec1.y - value);
        }

        public static Vector2D operator -(Vector2D vector)
        {
            return new Vector2D(-vector.x, -vector.y);
        }

        public static Vector2D operator *(Vector2D vec1, Vector2D vec2)
        {
            return new Vector2D(vec1.x * vec2.x, vec1.y * vec2.y);
        }

        public static Vector2D operator *(Vector2D vec1, float value)
        {
            return new Vector2D(vec1.x * value, vec1.y * value);
        }

        public static Vector2D operator /(Vector2D vec1, Vector2D vec2)
        {
            return new Vector2D(vec1.x / vec2.x, vec1.y / vec2.y);
        }

        public static Vector2D operator /(Vector2D vec1, float value)
        {
            float inverse = 1.0f / value;
            return vec1 * inverse;
        }

        public static bool operator ==(Vector2D vec1, Vector2D vec2)
        {
            if ((vec1.x == vec2.x) && (vec1.y == vec2.y))
                return true;
            else
                return false;
        }

        public static bool operator !=(Vector2D vec1, Vector2D vec2)
        {
            if (vec1.x != vec2.x || vec1.y != vec2.y)
                return true;
            else
                return false;
        }

        public static bool operator >(Vector2D vec1, Vector2D vec2)
        {
            if ((vec1.x > vec2.x) && (vec1.y > vec2.y))
                return true;
            else
                return false;
        }

        public static bool operator <(Vector2D vec1, Vector2D vec2)
        {
            if ((vec1.x < vec2.x) && (vec1.y < vec2.y))
                return true;
            else
                return false;
        }

        public static Vector2D Multiply(Vector2D vec1, Vector2D vec2)
        {
            return vec1 * vec2;
        }

        public void Inverse()
        {
            this.x *= -1;
            this.y *= -1;
        }

        public static Vector2D Inverse(Vector2D vector)
        {
            return -vector;
        }

        public static float Dot(Vector2D vec1, Vector2D vec2)
        {
            double dot = 0.0;
            dot += vec1.x * vec2.x;
            dot += vec1.y * vec2.y;
            return (float)dot;
        }

        public float Dot(Vector2D vector)
        {
            return Dot(this, vector);
        }

        public void Normalize()
        {
            // Will also work for zero-sized vectors, but will change nothing
            if (Length > float.Epsilon)
            {
                float inverseLength = 1.0f / Length;

                this.x *= inverseLength;
                this.y *= inverseLength;
            }
        }

        public override bool Equals(object obj)
        {
            if (obj is Vector2D)
                return (this == (Vector2D)obj);
            else
                return false;
        }

        public override int GetHashCode()
        {
            return (int)(x + y);
        }

    }
}
